package com.superhelper.task.job.stat;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.superhelper.common.domain.AuserShop;
import com.superhelper.common.domain.stat.StatDailyUser;
import com.superhelper.common.mapper.stat.StatDailyUserMapper;
import com.superhelper.common.utils.DateTimeUtil;
import com.superhelper.common.utils.JsonHelper;

public class StatDailyUserJob extends AbstractDailyJob implements SimpleJob {
    private final static Logger LOG = LoggerFactory.getLogger(StatDailyUserJob.class);

    @Autowired
    private StatDailyUserMapper statDailyUserMapper;

    @Override
    public void execute(ShardingContext shardingContext) {

        // String jobParam = shardingContext != null ?
        // shardingContext.getJobParameter()
        // : "{\"startDate\":\"2017-08-12\"}";
        String jobParam = shardingContext.getJobParameter();
        DateInfo di = calJobDate(jobParam, -1);
        LOG.info("startDate:{},endDate:{},statDate:{}", di.startDate, di.endDate, di.statDate);
        eachPlf(di.startDate, di.endDate, di.statDate);
        allPlf(di.startDate, di.endDate, di.statDate);
    }

    private void eachPlf(Date startDate, Date endDate, Date statDate) {

        // 活跃度
        List<StatDailyUser> actCnts = statDailyUserMapper.statActCnt(DateTimeUtil.addNDays(startDate, -30));
        List<StatDailyUser> slientCnts = statDailyUserMapper.statSlientCnt(DateTimeUtil.addNDays(startDate, -60),
                DateTimeUtil.addNDays(startDate, -30));
        List<StatDailyUser> loseCnts = statDailyUserMapper.statSlientCnt(DateTimeUtil.addNDays(startDate, -90),
                DateTimeUtil.addNDays(startDate, -60));

        eachPlfWithDays(startDate, endDate, statDate, actCnts, slientCnts, loseCnts, 1);
        eachPlfWithDays(startDate, endDate, statDate, actCnts, slientCnts, loseCnts, 7);
        eachPlfWithDays(startDate, endDate, statDate, actCnts, slientCnts, loseCnts, 30);

    }

    private void eachPlfWithDays(Date startDate, Date endDate, Date statDate, List<StatDailyUser> actCnts,
            List<StatDailyUser> slientCnts, List<StatDailyUser> loseCnts, int preDays) {
        List<StatDailyUser> stats = statDailyUserMapper
                .statDailyUser(preDays == 0 ? startDate : DateTimeUtil.addNDays(startDate, -preDays + 1), endDate);
        if (CollectionUtils.isEmpty(stats)) {
            return;
        }
        for (StatDailyUser o : stats) {
            AuserShop shop = shopCache.getShop(o.getShopId(), o.getShopType());
            if (shop == null) {
                LOG.info("can't find ausershop, StatDailyOrder：{}", JsonHelper.toJson(o));
                continue;
            }
            o.setAuserId(shop.getAuserId().longValue());
            o.setaUserShopId(shop.getId());
            o.setStatDate(statDate);
            o.setPreDays(preDays);
            o.setDupCnt(0);
            o.setDupRate(0d);
            o.setActCnt(0);
            o.setSlientCnt(0);
            o.setLoseCnt(0);
        }
        fillActSlientLose(stats, actCnts, slientCnts, loseCnts);

        // 非当天，需要计算重复下单率
        if (preDays != 1) {
            List<StatDailyUser> dupStats = statDailyUserMapper
                    .statDupUser(DateTimeUtil.addNDays(startDate, -preDays + 1), endDate);
            for (StatDailyUser o : stats) {
                for (StatDailyUser u : dupStats) {
                    if (u.getShopId().equals(o.getShopId()) && u.getShopType().equals(o.getShopType())) {
                        o.setDupCnt(u.getDupCnt());
                        if (u.getCnt() == null || u.getCnt() == 0) {
                            o.setDupRate(0d);
                        } else {
                            BigDecimal bg = new BigDecimal(u.getDupCnt() / (u.getCnt() + 0.000000000001) * 100);
                            o.setDupRate(bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                        }
                        break;
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(stats)) {
            statDailyUserMapper.batchAdd(stats);
        }
    }

    // 当天同一个店所有平台的统计
    private void allPlf(Date startDate, Date endDate, Date statDate) {

        // 活跃度
        List<StatDailyUser> actCnts = statDailyUserMapper.statAllPlfActCnt(DateTimeUtil.addNDays(startDate, -30));
        List<StatDailyUser> slientCnts = statDailyUserMapper.statAllPlfSlientCnt(DateTimeUtil.addNDays(startDate, -60),
                DateTimeUtil.addNDays(startDate, -30));
        List<StatDailyUser> loseCnts = statDailyUserMapper.statAllPlfSlientCnt(DateTimeUtil.addNDays(startDate, -90),
                DateTimeUtil.addNDays(startDate, -60));

        allPlfWithDays(startDate, endDate, actCnts, slientCnts, loseCnts, 1);
        allPlfWithDays(startDate, endDate, actCnts, slientCnts, loseCnts, 7);
        allPlfWithDays(startDate, endDate, actCnts, slientCnts, loseCnts, 30);

    }

    private void allPlfWithDays(Date startDate, Date endDate, List<StatDailyUser> actCnts,
            List<StatDailyUser> slientCnts, List<StatDailyUser> loseCnts, int preDays) {
        // 当天的数据
        List<StatDailyUser> stats = statDailyUserMapper.statDailyAllPlfUser(startDate, endDate);
        for (StatDailyUser o : stats) {
            o.setaUserShopId(0L);// 同一个平台
            o.setPreDays(preDays);
            o.setStatDate(startDate);
            o.setDupCnt(0);
            o.setDupRate(0d);
            o.setActCnt(0);
            o.setSlientCnt(0);
            o.setLoseCnt(0);
        }
        fillAllPlfActSlientLose(stats, actCnts, slientCnts, loseCnts);

        // 非当天，需要计算重复下单率
        if (preDays != 1) {
            List<StatDailyUser> dupStats = statDailyUserMapper
                    .statAllPlfDupUser(DateTimeUtil.addNDays(startDate, -preDays + 1), endDate);
            for (StatDailyUser o : stats) {
                for (StatDailyUser u : dupStats) {
                    if (o.getAuserId().longValue() == u.getAuserId().longValue()) {
                        o.setDupCnt(u.getDupCnt());
                        if (o.getCnt() == null || o.getCnt() == 0) {
                            o.setDupRate(0d);
                        } else {
                            BigDecimal bg = new BigDecimal(o.getDupCnt() / (o.getCnt() + 0.000000000001) * 100);
                            o.setDupRate(bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                        }
                        break;
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(stats)) {
            statDailyUserMapper.batchAdd(stats);
        }
    }

    private void fillActSlientLose(List<StatDailyUser> stats, List<StatDailyUser> actCnts,
            List<StatDailyUser> slientCnts, List<StatDailyUser> loseCnts) {
        for (StatDailyUser o : stats) {
            for (StatDailyUser u : actCnts) {
                if (u.getShopId().equals(o.getShopId()) && u.getShopType().equals(o.getShopType())) {
                    o.setActCnt(u.getActCnt());
                    break;
                }
            }
            for (StatDailyUser u : slientCnts) {
                if (u.getShopId().equals(o.getShopId()) && u.getShopType().equals(o.getShopType())) {
                    o.setSlientCnt(u.getSlientCnt());
                    break;
                }
            }
            for (StatDailyUser u : loseCnts) {
                if (u.getShopId().equals(o.getShopId()) && u.getShopType().equals(o.getShopType())) {
                    // 因为流水顾客是调用的沉默顾客的方法，所以slientCnt就是loseCnt
                    o.setLoseCnt(u.getSlientCnt());
                    break;
                }
            }
        }
    }

    private void fillAllPlfActSlientLose(List<StatDailyUser> stats, List<StatDailyUser> actCnts,
            List<StatDailyUser> slientCnts, List<StatDailyUser> loseCnts) {
        for (StatDailyUser o : stats) {
            for (StatDailyUser u : actCnts) {
                if (o.getAuserId().longValue() == u.getAuserId().longValue()) {
                    o.setActCnt(u.getActCnt());
                    break;
                }
            }
            for (StatDailyUser u : slientCnts) {
                if (o.getAuserId().longValue() == u.getAuserId().longValue()) {
                    o.setSlientCnt(u.getSlientCnt());
                    break;
                }
            }
            for (StatDailyUser u : loseCnts) {
                if (o.getAuserId().longValue() == u.getAuserId().longValue()) {
                    // 因为流水顾客是调用的沉默顾客的方法，所以slientCnt就是loseCnt
                    o.setLoseCnt(u.getSlientCnt());
                    break;
                }
            }
        }
    }
}
